﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MaterialEditor
{
    public class RotateNode : Node
    {
        private NodeValue _result;
        public override NodeValue Result
        {
            get { return _result; }
        }

        private NodeValueType[][] _acceptTypes;
        public override NodeValueType[][] acceptTypes
        {
            get { return _acceptTypes; }
        }

        private InputSlot TextureSlot
        {
            get { return input[0]; }
        }

        private InputSlot DegresSlot
        {
            get { return input[1]; }
        }

        public RotateNode(int x, int y)
            : base(x, y)
        {
            input = new InputSlot[]
            {
                new InputSlot(this, null, "A"),
                new InputSlot(this, null, "Angle"),
            };

            TextureSlot.Connected += TextureSlot_Connected;
            DegresSlot.Connected += DegresSlot_Connected;

            TextureSlot.Disconnected += TextureSlot_Disconnected;
            DegresSlot.Disconnected += DegreesSlot_Disconnected;

            TextureSlot.ValueChanged += UpdateValue;
            DegresSlot.ValueChanged += UpdateValue;
            
            _acceptTypes = new NodeValueType[][]
            {
                new NodeValueType[] { NodeValueType.ValueTexture },
                new NodeValueType[] { NodeValueType.ValueFloat },
            };

            output = new InputSlot(this, null, "");

            Name = "Rotate";
        }

        void DegresSlot_Connected()
        {
            DegresSlot.ValueChanged += UpdateValue;
            DegresSlot.value.TimeChanged += UpdateTime;

            UpdateValue();
        }

        void TextureSlot_Connected()
        {
            TextureSlot.ValueChanged += UpdateValue;

            UpdateValue();
        }

        private void DegreesSlot_Disconnected()
        {
            if (DegresSlot.value != null)
            {
                DegresSlot.ValueChanged -= UpdateValue;
                DegresSlot.value.TimeChanged -= UpdateTime;
            }
        }

        void TextureSlot_Disconnected()
        {
            if (TextureSlot.value != null)
                TextureSlot.ValueChanged -= UpdateValue;
        }

        public override object Clone()
        {
            RotateNode n = new RotateNode((int)position.X, (int)position.Y);
            n._result = new NodeValue(_result);
            return n;
        }

        private Rotate rotate;

        private void UpdateValue()
        {
            if (!DegresSlot.isConnected || !TextureSlot.isConnected)
            {
                _result = null;
                return;
            }

            TextureContainer container = new TextureContainer(TextureSlot.value.Value as TextureContainer);
            rotate = new Rotate();
            rotate.rotation = MathHelper.ToRadians(DegresSlot.value.AsFloat());
            container.texture.effects += rotate;

            _result = new NodeValue(container);
        }

        private void UpdateTime()
        {
            if (!DegresSlot.isConnected || !TextureSlot.isConnected)
                return;

            rotate.rotation = MathHelper.ToRadians(DegresSlot.value.AsFloat());
        }
    }
}